
module dares.Ares;

import dares.Types;

enum {
	ARES_SUCCESS            = 0,

	ARES_ENODATA            = 1,
	ARES_EFORMERR           = 2,
	ARES_ESERVFAIL          = 3,
	ARES_ENOTFOUND          = 4,
	ARES_ENOTIMP            = 5,
	ARES_EREFUSED           = 6,

	ARES_EBADQUERY          = 7,
	ARES_EBADNAME           = 8,
	ARES_EBADFAMILY         = 9,
	ARES_EBADRESP           = 10,
	ARES_ECONNREFUSED       = 11,
	ARES_ETIMEOUT           = 12,
	ARES_EOF                = 13,
	ARES_EFILE              = 14,
	ARES_ENOMEM             = 15,
	ARES_EDESTRUCTION       = 16,
	ARES_EBADSTR            = 17,

	ARES_EBADFLAGS          = 18,

	ARES_ENONAME            = 19,
	ARES_EBADHINTS          = 20,

	ARES_ENOTINITIALIZED    = 21,

	ARES_ELOADIPHLPAPI           = 22,
	ARES_EADDRGETNETWORKPARAMS   = 23,

	ARES_ECANCELLED         = 24,

	ARES_FLAG_USEVC         = 1 << 0,
	ARES_FLAG_PRIMARY       = 1 << 1,
	ARES_FLAG_IGNTC         = 1 << 2,
	ARES_FLAG_NORECURSE     = 1 << 3,
	ARES_FLAG_STAYOPEN      = 1 << 4,
	ARES_FLAG_NOSEARCH      = 1 << 5,
	ARES_FLAG_NOALIASES     = 1 << 6,
	ARES_FLAG_NOCHECKRESP   = 1 << 7,

	ARES_OPT_FLAGS          = 1 << 0,
	ARES_OPT_TIMEOUT        = 1 << 1,
	ARES_OPT_TRIES          = 1 << 2,
	ARES_OPT_NDOTS          = 1 << 3,
	ARES_OPT_UDP_PORT       = 1 << 4,
	ARES_OPT_TCP_PORT       = 1 << 5,
	ARES_OPT_SERVERS        = 1 << 6,
	ARES_OPT_DOMAINS        = 1 << 7,
	ARES_OPT_LOOKUPS        = 1 << 8,
	ARES_OPT_SOCK_STATE_CB  = 1 << 9,
	ARES_OPT_SORTLIST       = 1 << 10,
	ARES_OPT_SOCK_SNDBUF    = 1 << 11,
	ARES_OPT_SOCK_RCVBUF    = 1 << 12,
	ARES_OPT_TIMEOUTMS      = 1 << 13,
	ARES_OPT_ROTATE         = 1 << 14,

	ARES_NI_NOFQDN                  = 1 << 0,
	ARES_NI_NUMERICHOST             = 1 << 1,
	ARES_NI_NAMEREQD                = 1 << 2,
	ARES_NI_NUMERICSERV             = 1 << 3,
	ARES_NI_DGRAM                   = 1 << 4,
	ARES_NI_TCP                     = 0,
	ARES_NI_UDP                     =ARES_NI_DGRAM,
	ARES_NI_SCTP                    = 1 << 5,
	ARES_NI_DCCP                    = 1 << 6,
	ARES_NI_NUMERICSCOPE            = 1 << 7,
	ARES_NI_LOOKUPHOST              = 1 << 8,
	ARES_NI_LOOKUPSERVICE           = 1 << 9,

	ARES_NI_IDN                     = 1 << 10,
	ARES_NI_IDN_ALLOW_UNASSIGNED    = 1 << 11,
	ARES_NI_IDN_USE_STD3_ASCII_RULES = 1 << 12,

	ARES_AI_CANONNAME               = 1 << 0,
	ARES_AI_NUMERICHOST             = 1 << 1,
	ARES_AI_PASSIVE                 = 1 << 2,
	ARES_AI_NUMERICSERV             = 1 << 3,
	ARES_AI_V4MAPPED                = 1 << 4,
	ARES_AI_ALL                     = 1 << 5,
	ARES_AI_ADDRCONFIG              = 1 << 6,

	ARES_AI_IDN                     = 1 << 10,
	ARES_AI_IDN_ALLOW_UNASSIGNED    = 1 << 11,
	ARES_AI_IDN_USE_STD3_ASCII_RULES = 1 << 12,
	ARES_AI_CANONIDN                = 1 << 13,
	
	ARES_GETSOCK_MAXNUM	= 16 ,
	ARES_LIB_INIT_NONE		= 0 ,
	ARES_LIB_INIT_WIN32		= 1 << 0 ,
}

const ARES_SOCKET_BAD	= -1 ;
alias ARES_LIB_INIT_WIN32 ARES_LIB_INIT_ALL;

extern(C) :

alias void function(void*,  ares_socket_t, c_int,c_int) ares_sock_state_cb;
alias void function(void *, c_int, c_int, ubyte*, c_int) ares_callback;
alias void function(void *,  c_int,  c_int, hostent*) ares_host_callback;
alias void function(void *,  c_int, c_int, char*, char*) ares_nameinfo_callback;
alias c_int  function(ares_socket_t,  c_int, void*) ares_sock_create_callback;

struct in_addr {
	ubyte[4]	_S6_u8;	
}
struct ares_in6_addr {
	union {
		ubyte[16] _S6_u8;
	} 
}

struct ares_addrttl {
	in_addr	ipaddr;
	c_int		ttl;
}

struct ares_addr6ttl {
	ares_in6_addr	ip6addr;
	c_int            	ttl;
}

struct ares_srv_reply {
	ares_srv_reply *	next;
	char*		host;
	c_ushort		priority;
	c_ushort          weight;
	c_ushort          port;
}

struct ares_mx_reply {
	ares_mx_reply*		next;
	char*			host;
	c_ushort			priority;
};

struct ares_txt_reply {
	ares_txt_reply*	next;
	ubyte*		txt;
	size_t		length;
}

struct ares_options {
	c_int			flags;
	c_int			timeout;
	c_int			tries;
	c_int			ndots;
	c_ushort		udp_port;
	c_ushort		tcp_port;
	c_int			socket_send_buffer_size;
	c_int			socket_receive_buffer_size;
	in_addr*		servers;
	c_int			nservers;
	char**		domains;
	c_int				ndomains;
	char*			lookups;
	ares_sock_state_cb	sock_state_cb;
	void*			sock_state_cb_data;
	apattern*			sortlist;
	c_int				nsort;
}

struct ares_addr_node {
	ares_addr_node*	next;
	c_int family;
	union {
		in_addr		addr4 ;
		ares_in6_addr	addr6 ;
	} //addr;
}




c_int ares_library_init(c_int flags);
void ares_library_cleanup();
char *ares_version(c_int*);
c_int ares_init(ares_channel *channelptr);
c_int ares_init_options(ares_channel *channelptr, ares_options *options, c_int optmask);
c_int ares_save_options(ares_channel channel, ares_options *options,  c_int *optmask);
void ares_destroy_options(ares_options *options);
c_int ares_dup(ares_channel *dest, ares_channel src);
void ares_destroy(ares_channel channel);
void ares_cancel(ares_channel channel);
void ares_set_socket_callback(ares_channel channel, ares_sock_create_callback callback, void *user_data);
void ares_send(ares_channel channel, ubyte *qbuf, c_int qlen, ares_callback callback, void *arg);
void ares_query(ares_channel channel, char *name, c_int dnsclass, c_int type, ares_callback callback, void *arg);
void ares_search(ares_channel channel, char *name, c_int dnsclass, c_int type, ares_callback callback, void *arg);
 void ares_gethostbyname(ares_channel channel, char *name,  c_int family, ares_host_callback callback,  void *arg);
 c_int ares_gethostbyname_file(ares_channel channel, char *name, c_int family, hostent **host);
 void ares_gethostbyaddr(ares_channel channel, void *addr, c_int addrlen, c_int family, ares_host_callback callback,  void *arg);
 void ares_getnameinfo(ares_channel channel, sockaddr *sa, ares_socklen_t salen, c_int flags, ares_nameinfo_callback callback, void *arg);
 c_int ares_fds(ares_channel channel, fd_set *read_fds, fd_set *write_fds);
 c_int ares_getsock(ares_channel channel, ares_socket_t *socks, c_int numsocks);
 timeval *ares_timeout(ares_channel channel, timeval *maxtv, timeval *tv);
 void ares_process(ares_channel channel, fd_set *read_fds, fd_set *write_fds);
 void ares_process_fd(ares_channel channel, ares_socket_t read_fd, ares_socket_t write_fd);
 c_int ares_mkquery( char *name, c_int dnsclass, c_int type, c_ushort id, c_int rd, ubyte **buf, c_int *buflen);
 c_int ares_expand_name( ubyte *encoded, ubyte *abuf, c_int alen, char **s, c_long *enclen);
 c_int ares_expand_string( ubyte *encoded, ubyte *abuf, c_int alen, ubyte **s, c_long *enclen);
 c_int ares_parse_a_reply( ubyte *abuf, c_int alen, hostent **host, ares_addrttl *addrttls, c_int *naddrttls);
 c_int ares_parse_aaaa_reply( ubyte *abuf, c_int alen, hostent **host, ares_addr6ttl *addrttls,  c_int *naddrttls);
 c_int ares_parse_ptr_reply( ubyte *abuf, c_int alen, void *addr, c_int addrlen, c_int family, hostent **host);
 c_int ares_parse_ns_reply( ubyte *abuf, c_int alen, hostent **host);
 c_int ares_parse_srv_reply( ubyte* abuf, c_int alen, ares_srv_reply** srv_out);
 c_int ares_parse_mx_reply( ubyte* abuf, c_int alen, ares_mx_reply** mx_out);
 c_int ares_parse_txt_reply( ubyte* abuf, c_int alen, ares_txt_reply** txt_out);
 void ares_free_string(void *str);
 void ares_free_hostent( hostent *host);
 void ares_free_data(void*dataptr);
 char *ares_strerror(c_int code);
 c_int ares_set_servers(ares_channel channel, ares_addr_node *servers);
 c_int ares_get_servers(ares_channel channel, ares_addr_node **servers);